
'use strict';
/*!
 * patch.cb-recent-fix.js
 * 让“最近使用”稳定记录所有点击的色块（包括右侧色盘网格）。
 * - 事件委托到色盘根节点（也监听 document 兜底），异步渲染也能捕获
 * - 多路提取色值：data-hex/data-color/...、CSS变量 --sw、computed background-color
 * - 本地存储兼容：rm.cb、CBX_RECENT、palette_recent_colors_v2
 * - UI：在 .cb-right 或 .cb-controls 下生成「最近使用」区域
 */
(function(){
  var MAX = 12;
  var KEY_OBJ = 'rm.cb';                 // { recent: [] }
  var KEY_ARR = 'CBX_RECENT';            // [ '#RRGGBB', ... ]
  var KEY_ALT = 'palette_recent_colors_v2'; // 兼容旧脚本

  function toHex(v){
    if(!v) return null;
    v = String(v).trim();

    // 如果是 css var(--xxx)
    if(/^var\(/i.test(v)){
      // 取计算后的值
      return null; // 交给后面的 computedStyle 兜底
    }

    // #RGB / #RRGGBB
    var m = v.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
    if(m){
      var hex = m[1];
      if(hex.length === 3){
        return ('#' + hex.split('').map(function(x){return x + x;}).join('')).toUpperCase();
      }
      return ('#' + hex).toUpperCase();
    }

    // rgb/rgba/space-separated
    var mrgb = v.replace(/\//g,'').match(/^rgba?\(([^)]+)\)$/i);
    if(mrgb){
      var parts = mrgb[1].split(/[,\s]+/).filter(Boolean);
      if(parts.length >= 3){
        var r = Math.round(Number(parts[0]));
        var g = Math.round(Number(parts[1]));
        var b = Math.round(Number(parts[2]));
        if([r,g,b].every(function(n){ return !isNaN(n) && n>=0 && n<=255; })){
          return '#' + [r,g,b].map(function(n){
            var s = n.toString(16).toUpperCase();
            return s.length===1 ? '0'+s : s;
          }).join('');
        }
      }
    }
    return null;
  }

  function pickColorFromEl(el){
    if(!el) return null;

    // 1) data-* 常见字段
    var ds = el.dataset || {};
    var keys = ['hex','color','col','c','sw','rgb'];
    for(var i=0;i<keys.length;i++){
      var k = keys[i];
      if(ds[k]){
        var d = toHex(ds[k]);
        if(d) return d;
      }
    }

    // 2) style 属性里可能直接写了背景色或 CSS 变量
    if(el.style){
      var tryInline = toHex(el.style.background) || toHex(el.style.backgroundColor);
      if(tryInline) return tryInline;
      var sv = el.style.getPropertyValue('--sw');
      var hv = toHex(sv);
      if(hv) return hv;
    }

    // 3) 计算样式（最终渲染）
    var cs = window.getComputedStyle(el);
    if(cs){
      var viaVar = cs.getPropertyValue('--sw') || cs.getPropertyValue('--c-swatch') || cs.getPropertyValue('--color');
      var vhex  = toHex(viaVar);
      if(vhex) return vhex;
      var bg = cs.backgroundColor || cs.background;
      var byBg = toHex(bg);
      if(byBg && byBg !== '#00000000') return byBg;
    }
    return null;
  }

  function findColorFromEventTarget(target, root){
    var node = target;
    while(node && node !== document && node !== root){
      // 典型色块类名
      if(node.classList){
        if(node.classList.contains('swatch') || node.classList.contains('sw') ||
           node.classList.contains('cb-cell') || node.classList.contains('cb-swatch') ||
           node.classList.contains('color') || node.classList.contains('color-item') ||
           node.classList.contains('palette-cell') || node.classList.contains('palette-item')){
          var c = pickColorFromEl(node);
          if(c) return c;
        }
      }
      // 即便没有类名，也尝试从任何块元素拿颜色
      var c2 = pickColorFromEl(node);
      if(c2) return c2;

      node = node.parentElement;
    }
    return null;
  }

  function readState(){
    var list = [];
    try{
      var obj = JSON.parse(localStorage.getItem(KEY_OBJ) || '{}');
      if(obj && Array.isArray(obj.recent)) list = list.concat(obj.recent);
    }catch(e){}
    try{
      var arr = JSON.parse(localStorage.getItem(KEY_ARR) || '[]');
      if(Array.isArray(arr)) list = list.concat(arr);
    }catch(e){}
    try{
      var arr2 = JSON.parse(localStorage.getItem(KEY_ALT) || '[]');
      if(Array.isArray(arr2)) list = list.concat(arr2);
    }catch(e){}
    // 规范化&去重（保留顺序，最新优先）
    var seen = {};
    var out = [];
    for(var i=list.length-1;i>=0;i--){
      var h = toHex(list[i]);
      if(!h) continue;
      if(!seen[h]){
        seen[h]=1;
        out.unshift(h);
      }
    }
    while(out.length > MAX) out.shift();
    return out;
  }

  function writeState(arr){
    // 同步三份
    var clean = [];
    var seen = {};
    for(var i=0;i<arr.length;i++){
      var h = toHex(arr[i]);
      if(h && !seen[h]){ seen[h]=1; clean.push(h); }
    }
    var obj = { recent: clean.slice() };
    try{ localStorage.setItem(KEY_OBJ, JSON.stringify(obj)); }catch(e){}
    try{ localStorage.setItem(KEY_ARR, JSON.stringify(clean)); }catch(e){}
    try{ localStorage.setItem(KEY_ALT, JSON.stringify(clean)); }catch(e){}
  }

  function pushColor(hex){
    var list = readState();
    var h = toHex(hex);
    if(!h) return;
    // 移除旧位置
    list = list.filter(function(x){ return x !== h; });
    list.push(h);
    while(list.length > MAX) list.shift();
    writeState(list);
    // 触发渲染
    refreshUI(activeRoot || document);
  }

  function renderRecent(container, colors){
    if(!container) return;

    // 优先使用站点已有容器（如果存在）：#cbx-swatches 或 #color-search .swatches
    var external = document.getElementById('cbx-swatches') || document.querySelector('#color-search .swatches');
    if(external){
      // 只渲染方块，不生成标题；保持站点原有样式
      external.innerHTML = '';
      colors.slice().reverse().forEach(function(hex){
        var b = document.createElement('button');
        b.type = 'button';
        b.className = 'sw';
        b.setAttribute('data-hex', hex);
        b.setAttribute('title', hex);
        b.style.width='36px'; b.style.height='36px'; b.style.borderRadius='8px';
        b.style.border='1px solid rgba(255,255,255,.12)'; b.style.background = hex; b.style.margin='0 12px 12px 0';
        external.appendChild(b);
      });
      // 点击回填
      external.addEventListener('click', function(e){
        var t = e.target; if(!(t instanceof Element)) return;
        var hx = t.getAttribute('data-hex') || (t.style && (t.style.background || t.style.backgroundColor));
        if(!hx) return;
        applyColor(hx, container);
        pushColor(hx);
      }, { passive:true });
      return;
    }

    // 默认：在面板内创建 .cb-recent
    var section = container.querySelector('.cb-recent');
    if(!section){
      section = document.createElement('div');
      section.className = 'cb-recent';
      var h = document.createElement('h4'); h.textContent = '最近使用';
      var row = document.createElement('div'); row.className = 'row';
      section.appendChild(h); section.appendChild(row); container.appendChild(section);
    }
    var rowEl = section.querySelector('.row');
    rowEl.innerHTML = '';
    colors.slice().reverse().forEach(function(hex){
      var b = document.createElement('button');
      b.type='button'; b.className='sw'; b.dataset.hex = hex;
      b.style.width='36px'; b.style.height='36px'; b.style.borderRadius='8px';
      b.style.border='1px solid rgba(255,255,255,.12)'; b.style.background=hex; b.style.margin='0 12px 12px 0';
      rowEl.appendChild(b);
    });
    rowEl.addEventListener('click', function(e){
      var t = e.target; if(!(t instanceof Element)) return;
      var hx = t.dataset && t.dataset.hex;
      if(!hx) hx = (t.style && (t.style.background || t.style.backgroundColor)) || null;
      if(!hx) return;
      applyColor(hx, container);
      pushColor(hx);
    }, { passive:true });
    }

  function getPanelRoot(root){
    if(!root) return null;
    // 优先：页面现有“右侧面板/控制区/最近使用容器”
    var target = document.getElementById('cbx-swatches') ||
                 document.querySelector('#color-search .swatches') ||
                 root.querySelector('.cb-right') ||
                 root.querySelector('.cb-controls') ||
                 document.querySelector('#hero .right') ||
                 document.querySelector('#hero .left');
    return target || root;
    }

  function refreshUI(root){
    var panel = getPanelRoot(root);
    if(!panel) return;
    renderRecent(panel, readState());
  }

  function applyColor(hex, root){
    var h = toHex(hex);
    if(!h) return;

    // 同步到 HEX 输入框（如果有）
    var input = (root && root.querySelector('#cb-hex-input')) || document.querySelector('#cb-hex-input');
    if(input){
      input.value = h;
      try{
        input.dispatchEvent(new Event('input', {bubbles:true}));
        input.dispatchEvent(new Event('change', {bubbles:true}));
      }catch(e){}
    }

    // 同步到页面其它可能的 UI（左侧方块预览）
    try{
      var preview = (root && root.querySelector('.cb-picked .color')) || document.querySelector('.cb-picked .color');
      if(preview) preview.style.background = h;
    }catch(e){}
  }

  // 监听点击：任何在色盘区域的点击都尝试取色
  var activeRoot = null;
  function install(root){
    if(!root) return;
    activeRoot = root;

    // 初始渲染
    refreshUI(root);

    // 捕获 palette 网格点击（包括截图红框区域）
    ['click','pointerdown'].forEach(function(type){ root.addEventListener(type, function(e){
      var target = e.target;
      if(!(target instanceof Element)) return;
      var hx = findColorFromEventTarget(target, root);
      if(!hx) return;
      applyColor(hx, root);
      pushColor(hx);
    }, true); }); // useCapture 确保先于内部 handler 获取到事件

    // HEX 输入也会刷新「最近使用」
    var input = root.querySelector('#cb-hex-input');
    if(input){
      input.addEventListener('change', function(){
        var h = toHex(input.value);
        if(h) pushColor(h);
      });
    }
  }

  // 等待根节点出现
  function waitForRoot(){
    var tryFind = function(){
      var r = document.getElementById('color-board') ||
              document.getElementById('cb') ||
              document.getElementById('color-search') ||
              document.querySelector('#tp-colorboard') ||
              document.querySelector('.color-board') ||
              document.querySelector('[data-role="color-board"]');
      return r || null;
    };
    var r0 = tryFind();
    if(r0){ install(r0); return; }

    var mo = new MutationObserver(function(){
      var r1 = tryFind();
      if(r1){
        mo.disconnect();
        install(r1);
      }
    });
    mo.observe(document.documentElement || document.body, {childList:true, subtree:true});
  }

  if(document.readyState === 'loading'){
    document.addEventListener('DOMContentLoaded', waitForRoot, {once:true});
  }else{
    waitForRoot();
  }
})();
